package com.itheima.project.face.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.project.constant.file.FileCacheConstant;
import com.itheima.project.core.enums.file.FileEnum;
import com.itheima.project.exception.ProjectException;
import com.itheima.project.face.FileFace;
import com.itheima.project.pojo.File;
import com.itheima.project.service.IFileService;
import com.itheima.project.utils.BeanConv;
import com.itheima.project.utils.EmptyUtil;
import com.itheima.project.utils.EncodesUtil;
import com.itheima.project.utils.ExceptionsUtil;
import com.itheima.project.vo.file.FileVo;
import com.itheima.project.vo.file.UploadMultipartFile;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Set;

/**
 * @ClassName FileFaceImpl.java
 * @Description 附件接口实现
 */
@Slf4j
@Component
public class FileFaceImpl implements FileFace {

    @Autowired
    IFileService fileService;

    @Override
    @Cacheable(value = FileCacheConstant.BASIC,key = "#fileId")
    public FileVo downLoad(Long fileId) throws ProjectException {
        try {
            FileVo fileVo = fileService.downLoad(fileId);
            return fileVo;
        } catch (Exception e) {
            log.error("文件下载传异常：{}", ExceptionsUtil.getStackTraceAsString(e));
            throw new ProjectException(FileEnum.DOWNLOAD_FAIL);
        }
    }

    @Override
    @Caching(evict = {@CacheEvict(value = FileCacheConstant.PAGE,allEntries = true),
            @CacheEvict(value = FileCacheConstant.BUSINESS_KEY,allEntries = true)},
        put={@CachePut(value =FileCacheConstant.BASIC,key = "#result.id")})
    @Transactional
    public FileVo upLoad(UploadMultipartFile multipartFile, FileVo fileVo) throws ProjectException {
        try {
            String base64Image = EncodesUtil.encodeBase64(multipartFile.getFileByte());
            File file = fileService.upLoad(multipartFile, fileVo);
            FileVo fileVoResult = BeanConv.toBean(file, FileVo.class);
            fileVoResult.setBase64Image(base64Image);
            return fileVoResult;
        } catch (ProjectException e) {
            log.error("文件上传操作失败：{}", ExceptionsUtil.getStackTraceAsString(e));
            throw e;
        } catch (Exception e) {
            log.error("文件上传异常：{}", ExceptionsUtil.getStackTraceAsString(e));
            throw new ProjectException(FileEnum.UPLOAD_FAIL,e.getMessage());
        }
    }

    @Override
    @Cacheable(value = FileCacheConstant.BUSINESS_KEY,key = "#businessId")
    public List<FileVo> findFileVoByBusinessId(Long businessId) throws ProjectException {
        try {
            List<File> filees = fileService.findFileVoByBusinessId(businessId);
            return BeanConv.toBeanList(filees,FileVo.class);
        }catch (Exception e){
            log.error("查询业务对应附件：{}异常：{}", businessId,ExceptionsUtil.getStackTraceAsString(e));
            throw new ProjectException(FileEnum.SELECT_FILE_BUSINESSID_FAIL);
        }
    }

    @Override
    @Caching(evict = {@CacheEvict(value = FileCacheConstant.PAGE,allEntries = true),
            @CacheEvict(value = FileCacheConstant.BASIC,key = "#fileVo.id"),
            @CacheEvict(value = FileCacheConstant.BUSINESS_KEY,key = "#fileVo.businessId",beforeInvocation = true)})
    @Transactional
    public List<FileVo>  bindBusinessId(FileVo fileVo) throws ProjectException {
        try {
            fileService.bindBusinessId(fileVo);
            return findFileVoByBusinessId(fileVo.getBusinessId());
        } catch (Exception e) {
            log.error("绑定业务：{}异常：{}", fileVo.toString(),ExceptionsUtil.getStackTraceAsString(e));
            throw new ProjectException(FileEnum.BIND_FAIL);
        }
    }

    @Override
    @Transactional
    public Boolean replaceBindBusinessId(FileVo fileVo) {

        //如果附件Id不变则不需要修改
        File file = fileService.getById(fileVo.getId());
//        if (EmptyUtil.isNullOrEmpty(file) || EmptyUtil.isNullOrEmpty(file.getBusinessId())) {
//            log.info("附件可能不存在，fileId:{}",fileVo.getId());
//            return false;
//        }
        // 如果新变化的品牌图片  是未携带businessId的，上面的判断会直接返回
        if (EmptyUtil.isNullOrEmpty(file)) {
            log.info("附件可能不存在，fileId:{}",fileVo.getId());
            return false;
        }
        // 如果文件 有业务ID 判断业务ID是否和老业务ID一致
        if (file.getBusinessId()!=null && fileVo.getBusinessId().longValue() == file.getBusinessId().longValue()) {
            return true;
        }
        //删除老图片
        Boolean flag = deleteFileVoByBusinessId(fileVo.getBusinessId());
        //绑定新图片
        List<FileVo> fileVos = bindBusinessId(fileVo);
        if (EmptyUtil.isNullOrEmpty(fileVos)){
            flag = false;
        }
        return flag;
    }

    @Override
    @Transactional
    public Boolean replaceBindBatchBusinessId(List<FileVo> fileVos) {
        //删除老图片
        Boolean flag = deleteFileVoByBusinessId(fileVos.get(0).getBusinessId());
        //绑定新图片
        List<FileVo> fileVosResult = bindBatchBusinessId(fileVos);
        if (EmptyUtil.isNullOrEmpty(fileVosResult)){
            flag = false;
        }
        return flag;
    }


    @Override
    @Caching(evict = {@CacheEvict(value = FileCacheConstant.PAGE,allEntries = true),
        @CacheEvict(value = FileCacheConstant.BASIC,allEntries = true),
        @CacheEvict(value = FileCacheConstant.BUSINESS_KEY,key = "#fileVos.get(0).getBusinessId()",beforeInvocation = true)})
    @Transactional
    public List<FileVo> bindBatchBusinessId(List<FileVo> fileVos) throws ProjectException {
        Long businessId = fileVos.get(0).getBusinessId();
        if (EmptyUtil.isNullOrEmpty(businessId)) {
            throw new ProjectException(FileEnum.SELECT_BUSUBBESSID_FAIL);
        }
        try {
            fileService.updateBatchById(BeanConv.toBeanList(fileVos, File.class));
            return findFileVoByBusinessId(businessId);
        } catch (Exception e) {
            log.error("绑定业务：{}异常：{}", fileVos.toString(),ExceptionsUtil.getStackTraceAsString(e));
            throw new ProjectException(FileEnum.BIND_FAIL);
        }
    }

    @Override
    @Cacheable(value = FileCacheConstant.PAGE,key ="#pageNum+'-'+#pageSize+'-'+#fileVo.hashCode()")
    public Page<FileVo> findFileVoPage(FileVo fileVo, int pageNum, int pageSize) throws ProjectException {
        try {
            Page<File> page = fileService.findFileVoPage(fileVo, pageNum, pageSize);
            Page<FileVo> pageVo =BeanConv.toPage(page,FileVo.class);
            return pageVo;
        }catch (Exception e){
            log.error("查询附件列表异常：{}", ExceptionsUtil.getStackTraceAsString(e));
            throw new ProjectException(FileEnum.PAGE_FAIL);
        }
    }

    @Override
    public Set<Long> findBusinessIdAll() {
        try {
            return fileService.findBusinessIdAll();
        }catch (Exception e){
            log.error("查询附件列表异常：{}", ExceptionsUtil.getStackTraceAsString(e));
            throw new ProjectException(FileEnum.SELECT_BUSUBBESSID_FAIL);
        }
    }

    @Override
    @Caching(evict = {@CacheEvict(value = FileCacheConstant.PAGE,allEntries = true),
            @CacheEvict(value = FileCacheConstant.BUSINESS_KEY,allEntries = true),
            @CacheEvict(value = FileCacheConstant.BASIC,allEntries = true)})
    @Transactional
    public Boolean deleteFileVo(String[] checkedIds) throws ProjectException {
        try {
            return fileService.deleteFile(checkedIds);
        }catch (Exception e){
            log.error("删除业务对应附件：{}",ExceptionsUtil.getStackTraceAsString(e));
            throw new ProjectException(FileEnum.DELETE_FILE_BUSINESSID_FAIL);
        }
    }

    @Override
    @Caching(evict = {@CacheEvict(value = FileCacheConstant.PAGE,allEntries = true),
            @CacheEvict(value = FileCacheConstant.BUSINESS_KEY,key = "#businessId"),
            @CacheEvict(value = FileCacheConstant.BASIC,allEntries = true)})
    @Transactional
    public Boolean deleteFileVoByBusinessId(Long businessId) throws ProjectException {
        try {
            return fileService.deleteFileVoByBusinessId(businessId);
        }catch (Exception e){
            log.error("删除业务对应附件：{}失败",businessId);
            throw new ProjectException(FileEnum.DELETE_FILE_BUSINESSID_FAIL);
        }
    }
}
